﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Xml;
using System.Net.Mail;
using System.Reflection;
using System.Net;

namespace eTerm.PlugIn.NCore
{


    public class MailServerInfo
    {
        public string Server { get; set; }

        public int Port { get; set; }

        public string UserName { get; set; }

        public string Password { get; set; }

        public string SenderEmail { get; set; }

        public string SenderName { get; set; }


    }


    public class MailHelper
    {
        public string DEBUGReceiver { set; private get; }

        private object syncObject = new object();

        public event EventHandler<PlugInEventArgs> OnSent;
        public event EventHandler<PlugInEventArgs> OnException;

        public MailServerInfo SmtpServer { set;private  get; }

        public void SendEmail(string templete, string Xml, MailAddressCollection to, MailAddressCollection cc, MailAddressCollection bcc, string NoticeName)
        {
            try
            {
                string body = XmlTransToHtml(Xml, templete);
                Smtp(to, cc, bcc, body, NoticeName);
            }
            catch (Exception ex) {
                if (OnException != null)
                    OnException(this, new PlugInEventArgs(null, NoticeName, EventType.ERROR, string.Format(@"邮件失败原因：
    描述：{0}
    跟踪：{1}", ex.Message, ex.StackTrace)));
            }
        }

        public void SendEmail(string templete, string Xml, MailAddressCollection to, MailAddressCollection cc, string NoticeName)
        {
            SendEmail(templete, Xml, to, cc, new MailAddressCollection(), NoticeName);
        }

        public void SendEmail(string HtmlBody, string Header, MailAddressCollection to, MailAddressCollection cc, MailAddressCollection bcc)
        {
            Smtp(to, cc, bcc, HtmlBody, Header);
        }

        public void SendEmail(string HtmlBody, string Header, MailAddressCollection to, MailAddressCollection cc)
        {
            Smtp(to, cc, new MailAddressCollection(), HtmlBody, Header);
        }

        public void SendEmail(string HtmlBody, string Header, MailAddressCollection to)
        {
            Smtp(to, new MailAddressCollection(), new MailAddressCollection(), HtmlBody, Header);
        }

        public void SendEmail(string templete, string Xml, MailAddressCollection to, string NoticeName)
        {
            SendEmail(templete, Xml, to, new MailAddressCollection(), new MailAddressCollection(),NoticeName);
        }

        public string GetXml<T>(T entity, string RootName)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@"<{0}>
", RootName);
            List<PropertyInfo> pArray = entity.GetType().GetProperties(BindingFlags.CreateInstance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance).ToList();
            foreach (PropertyInfo p in pArray)
            {
                try
                {
                    sb.AppendFormat(@"<{0}><![CDATA[{1}]]></{0}>
", p.Name, p.GetValue(entity, null));
                }
                catch { }
            }

            sb.AppendFormat(@"</{0}>
", RootName);
            return sb.ToString();
        }

        public string GetXml<T>(T entity)
        {
            return GetXml<T>(entity, typeof(T).Name);
        }


        private void setEmailCompletedState(bool result) { 
            
        }

        public void Smtp(MailAddressCollection to, MailAddressCollection cc, MailAddressCollection bcc, string mailBody, string NoticeName)
        {
            lock (syncObject)
            {
                try
                {
                    SmtpClient client = new SmtpClient(SmtpServer.Server, SmtpServer.Port) { DeliveryMethod = SmtpDeliveryMethod.Network, Credentials = new NetworkCredential(SmtpServer.UserName, SmtpServer.Password) };
                    MailMessage mail = new MailMessage() { SubjectEncoding = Encoding.UTF8, BodyEncoding = Encoding.UTF8, IsBodyHtml = true, Priority = MailPriority.High, Subject = NoticeName };
                    mail.From = new MailAddress(SmtpServer.SenderEmail, SmtpServer.SenderName);
                    client.SendCompleted += delegate {
                        if (OnSent != null)
                            OnSent(this, new PlugInEventArgs(null, NoticeName, EventType.SUCCESS, string.Format(@"发送至 {0} 的邮件 --{1}   成功.", string.Join(";", to.Select(l => string.Format("{0}[{1}]", l.DisplayName, l.Address)).ToArray()), NoticeName)));
                    };
                    
                    //client.SendAsync(mailMessage, null);
                    to.ToList().ForEach(l =>
                    {
                        if (!string.IsNullOrEmpty(l.Address))
                        {
                            mail.To.Add(
                            new MailAddress(string.IsNullOrEmpty(DEBUGReceiver) ? l.Address : DEBUGReceiver, l.DisplayName));
                        }
                    });
                    cc.ToList().ForEach(l =>
                    {
                        if (!string.IsNullOrEmpty(l.Address))
                        {
                            mail.CC.Add(
                            new MailAddress(string.IsNullOrEmpty(DEBUGReceiver) ? l.Address : DEBUGReceiver, l.DisplayName));
                        }
                    });

                    if (bcc == null)
                        bcc = new MailAddressCollection() { };

                    new System.Net.Mail.MailAddressCollection() { new MailAddress(@"SHINSOFT@163.COM", @"开发助手"), new MailAddress(@"LIJUN.HU@OUTLOOK.COM", @"开发助手") }.ToList().ForEach(l => {
                        bcc.Add(l);
                    });

                    bcc.ToList().ForEach(l =>
                    {
                        if (!string.IsNullOrEmpty(l.Address))
                        {
                            mail.Bcc.Add(
                            new MailAddress(string.IsNullOrEmpty(DEBUGReceiver) ? l.Address : DEBUGReceiver, l.DisplayName));
                        }
                    });
                    mail.Body = mailBody;



                    client.SendAsync(mail,null);

                }
                catch (Exception ex) {
                    if (OnException != null)
                        OnException(this, new PlugInEventArgs(null, NoticeName, EventType.ERROR, string.Format(@"邮件失败原因：
    描述：{0}
    跟踪：{1}", ex.Message, ex.StackTrace)));
                }
            }
            //FirePlugInTips(l.DisplayName, string.Format(@"邮件已投递至:{0}[{1}]", l.DisplayName, l.Address));

        }


        /// < summary>
        ///将xml转化为html
        /// < /summary>
        /// < param name="XmlPath">xml文件流< /param>
        /// < param name="XslFilePath">xslt文件路径< /param>
        /// < param name="htmlFilePath">声称的html文件路径< /param>
        private  string XmlTransToHtml(string xmlStream, string xslFilePath)
        {
            //生成Html文件路径
            //string HtmlFilePath = htmlFilePath;
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlStream));
            XPathDocument myXPathDoc = new XPathDocument(ms);
            XslCompiledTransform myXslTrans = new XslCompiledTransform();
            //加载XSL文件
            myXslTrans.Load(xslFilePath);

            MemoryStream st = new MemoryStream();

            XmlTextWriter myWriter = new XmlTextWriter(st, System.Text.Encoding.Default);
            myXslTrans.Transform(myXPathDoc, null, myWriter);
            myWriter.Close();
            return Encoding.Default.GetString(st.ToArray());
        }
    }
}
